/**
 * VERSION: 1.811
 * DATE: 1/12/2010
 * AS3 
 * UPDATES AND DOCUMENTATION AT: http://blog.greensock.com/transformmanageras3/
 **/
package com.greensock.transform {
	
	import com.greensock.events.TransformEvent;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.getDefinitionByName;
	
	import mx.containers.Canvas;
	import mx.core.UITextField;
	
	[Event(name="tmMove", type="com.greensock.events.TransformEvent")]
	[Event(name="tmScale", type="com.greensock.events.TransformEvent")]
	[Event(name="tmRotate", type="com.greensock.events.TransformEvent")]
	[Event(name="tmSelect", type="com.greensock.events.TransformEvent")]
	[Event(name="tmMouseDown", type="com.greensock.events.TransformEvent")]
	[Event(name="tmSelectMouseDown", type="com.greensock.events.TransformEvent")]
	[Event(name="tmSelectMouseUp", type="com.greensock.events.TransformEvent")]
	[Event(name="tmDelete", type="com.greensock.events.TransformEvent")]
	[Event(name="tmSelectionChange", type="com.greensock.events.TransformEvent")]
	[Event(name="tmDeselect", type="com.greensock.events.TransformEvent")]
	[Event(name="tmClickOff", type="com.greensock.events.TransformEvent")]
	[Event(name="tmUpdate", type="com.greensock.events.TransformEvent")]
	[Event(name="tmDepthChange", type="com.greensock.events.TransformEvent")]
	[Event(name="tmDestroy", type="com.greensock.events.TransformEvent")]
	[Event(name="tmFinishInteractiveMove", type="com.greensock.events.TransformEvent")]
	[Event(name="tmFinishInteractiveScale", type="com.greensock.events.TransformEvent")]
	[Event(name="tmFinishInteractiveRotate", type="com.greensock.events.TransformEvent")]
	[Event(name="tmDoubleClick", type="com.greensock.events.TransformEvent")]
	
/**
 * FlexTransformManager works with TransformManager and makes it easy to add interactive scaling/rotating/moving of 
 * DisplayObjects to your Flex application.	It uses an intuitive interface that's similar to most modern drawing applications. 
 * When the user clicks on a managed DisplayObject, a selection box will be drawn around it along with 8 handles for 
 * scaling/rotating. When the mouse is placed just outside of any of the scaling handles, the cursor will change 
 * to indicate that they're in rotation mode. Just like most other applications, the user can hold down the SHIFT 
 * key to select multiple items, to constrain scaling proportions, or to limit the rotation to 45 degree increments. 
 * All the work is done by the TransformManager instance which is compatible with Flash, but FlexTransformManager is 
 * basically a wrapper that makes it compatible with Flex.<br /><br />
 *  
 * <b>FEATURES INCLUDE:</b><br />
 * <ul>
 *	 <li> Select multiple items and scale/rotate/move them all simultaneously.</li>
 *	 <li> Perform virtually any action (transformations, selections, etc.) through code.</li>
 *	 <li> Depth management which allows you to programmatically push the selected items forward or backward in the stacking order</li>
 *	 <li> Set minScaleX, maxScaleX, minScaleY, and maxScaleY properties on each item </li>
 *	 <li> Arrow keys move the selection </li>
 *	 <li> You can set the scaleMode of any TransformItem to SCALE_WIDTH_AND_HEIGHT so that the width/height properties are altered instead of scaleX/scaleY. This can be helpful for text-related components because altering the width/height changes only the container's dimensions while retaining the text's size.</li>
 *	 <li> There is a 10-pixel wide draggable edge around around the border that users can drag. This is particularly helpful with TextFields/TextAreas.</li>
 *	 <li> Define bounds within which the DisplayObjects must stay, and FlexTransformManager will not let the user scale/rotate/move them beyond those bounds</li>
 *	 <li> Automatically bring the selected item(s) to the front in the stacking order </li>
 *	 <li> The DELETE and BACKSPACE keys can be used to delete the selected DisplayObjects </li>
 *	 <li> Lock certain kinds of transformations like rotation, scale, and/or movement </li>
 *	 <li> Lock the proportions of the DisplayObjects so that users cannot distort them when scaling</li>
 *	 <li> Scale from the DisplayObject's center or from its corners</li>
 *	 <li> Listen for Events like SCALE, MOVE, ROTATE, SELECT, DESELECT, SELECTION_CHANGE, DEPTH_CHANGE, CLICK_OFF, FINISH_INTERACTIVE_MOVE, FINISH_INTERACTIVE_SCALE, FINISH_INTERACTIVE_ROTATE, DOUBLE_CLICK, and DESTROY </li>
 *	 <li> Set the selection box line color and handle thickness</li>
 *	 <li> Cursor will automatically change to indicate scale or rotation mode</li>
 * 	 <li> Optionally hide the center handle</li>
 *	 <li> VERY easy to use. In fact, all it takes is one line of code to get it up and running with the default settings. </li>
 * </ul>
 * 
 * <b>NOTES / LIMITATIONS</b>:<br />
 * <ul>
 * 		<li> All DisplayObjects that are managed by a particular FlexTransformManager instance must have the same parent (you can create multiple FlexTransformManager instances if you want)</li>
 * 		<li> TextFields cannot be flipped (have negative scales).</li>
 * 		<li> TextFields cannot be skewed. Therefore, when a TextField is part of a multi-selection, scaling will be disabled because it could skew the TextField (imagine if a TextField is at a 45 degree angle, and then you selected another item and scaled vertically - your TextField would end up getting skewed).</li>
 * 		<li> Due to a limitation in the way Flash reports bounds, items that are extremely close or exactly on top of a boundary (if you define bounds) will be moved about 0.1 pixel away from the boundary when you select them. If an item fills the width and/or height of the bounds, it will be scaled down very slightly (about 0.2 pixels total) to move it away from the bounds and allow accurate collision detection.</li>
 * </ul><br />
 * 
 * <b>EXAMPLES:</b><br /><br />
 * To make two Images (myImage1 and myImage2) transformable using the default settings:<br /><br /><code>
 * 
 * 	&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;br /&gt;<br />
 * 	&lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:transform="com.greensock.transform.*"&gt;<br />
 * 		&lt;transform:FlexTransformManager id="myManager" width="500" height="500"&gt; <br />
 * 			&lt;mx:Image source="../libs/image1.png" id="myImage1" autoLoad="true" x="100" y="100" /&gt; <br />
 * 			&lt;mx:Image source="../libs/image2.png" id="myImage2" autoLoad="true" x="0" y="300" /&gt; <br />
 * 		&lt;/transform:FlexTransformManager&gt;<br />
 * 	&lt;/mx:Application&gt;<br /><br /></code>
 * 
 * 
 * To make the two Images transformable, constrain their scaling to be proportional (even if the user is not holding
 * down the shift key), call the onScale function everytime one of the objects is scaled, lock the rotation value of each 
 * Image (preventing rotation), and allow the delete key to appear to delete the selected Image from the stage:<br /><br /><code>
 * 
 * 	&lt;?xml version="1.0" encoding="utf-8"?&gt;<br />
 * 	&lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:transform="com.greensock.transform.*" creationComplete="init()"&gt;<br />
 * 		&lt;mx:Script&gt;<br />
 * 			&lt;![CDATA[<br />
 * 				import com.greensock.events.TransformEvent;<br />
 * 				private function init():void {<br />
 * 					myManager.addEventListener(TransformEvent.SCALE, onScale, false, 0, true);<br />
 * 				}<br />
 * 				private function onScale($e:TransformEvent):void {<br />
 * 					trace("Scaled " + $e.items.length + " items");<br />
 * 				}<br />
 * 			]]&gt;<br />
 * 		&lt;/mx:Script&gt;<br />
 * 		&lt;transform:FlexTransformManager id="myManager" width="500" height="500" allowDelete="true" constrainScale="true" lockRotation="true"&gt;<br />
 * 			&lt;mx:Image source="../libs/image1.png" id="image1" autoLoad="true" x="50" y="50" /&gt;<br />
 * 			&lt;mx:Image source="../libs/image1.png" id="image2" autoLoad="true" x="100" y="200" /&gt;<br />
 * 		&lt;/transform:FlexTransformManager&gt;<br />
 * 	&lt;/mx:Application&gt;<br /><br /></code>
 * 
 * <b>Copyright 2010, GreenSock. All rights reserved.</b> This work is subject to the terms in <a href="http://www.greensock.com/eula.html">http://www.greensock.com/eula.html</a> or for corporate Club GreenSock members, the software agreement that was issued with the corporate membership.
 * 
 * @author Jack Doyle, jack@greensock.com
 */
	public class FlexTransformManager extends Canvas {
		public static const VERSION:Number = 1.81;
		/** @private **/
		protected static var _flexTF:UITextField; //Just ensures that the UITextField class is embedded for use in TransformItem.
		/** @private **/
		protected static var _initted:Boolean;
		/** @private **/
		protected static var _nonStandardScalingClasses:Array; //Classes that will be treated like TextFields where their width and height is scaled instead of scaleX/scaleY
		
		/** @private **/
		protected var _manager:TransformManager;
		
		/**
		 * Constructor
		 * 
		 * @param $vars An object specifying any properties that should be set upon instantiation, like <code>{scaleFromCenter:true, lockRotation:true, bounds:new Rectangle(0, 0, 500, 300)}</code>.
		 */
		public function FlexTransformManager($vars:Object = null) {
			super();
			if (!_initted) {
				if (TransformManager.VERSION < 1.81) {
					trace("TransformManager Error: You have an outdated TransformManager-related class file. You may need to clear your ASO files. Please make sure you're using the latest version of TransformManager, FlexTransformItem, and FlexTransformItemTF, available from www.greensock.com.");
				}
				_nonStandardScalingClasses = [];
				
				//these classes will be scaled by changing their width/height instead of scaleX/scaleY (this is preferred for certain text-related components so that only the container resizes instead of the text.
				addNonStandardScalingClass("mx.controls.TextArea", TransformManager.SCALE_WIDTH_AND_HEIGHT, true);
				addNonStandardScalingClass("mx.controls.TextInput", TransformManager.SCALE_WIDTH_AND_HEIGHT, true);
				addNonStandardScalingClass("mx.core.UITextField", TransformManager.SCALE_WIDTH_AND_HEIGHT, true);
				addNonStandardScalingClass("mx.controls.RichTextEditor", TransformManager.SCALE_WIDTH_AND_HEIGHT, true);
				addNonStandardScalingClass("mx.controls.Label", TransformManager.SCALE_WIDTH_AND_HEIGHT, false);
				
				_initted = true;
			}
			_manager = new TransformManager($vars);
			super.verticalScrollPolicy = "off";
			super.horizontalScrollPolicy = "off";
			this.addEventListener(Event.ADDED_TO_STAGE, onAddToStage, false, 1, true);
		}
		
		/** @private **/
		protected static function addNonStandardScalingClass($classPath:String, $scaleMode:String, $hasSelectableText:Boolean):void {
			var type:Object;
			try {
				type = getDefinitionByName($classPath);
			} catch ($e:Error) {
				
			}
			if (type != null) {
				_nonStandardScalingClasses[_nonStandardScalingClasses.length] = {type:type, scaleMode:$scaleMode, hasSelectableText:$hasSelectableText};
			}
		}
		
		/** @private **/
		protected function onAddToStage($e:Event):void {
			for (var i:int = this.numChildren - 1; i > -1; i--) {
				autoAddChild(this.getChildAt(i));
			}
			_manager.bounds = new Rectangle(0, 0, this.width, this.height);
		}
		
		/**
		 * In order for a DisplayObject to be managed by FlexTransformManger, it must first be added via <code>addItem()</code>. When the
		 * DisplayObject is added, a TransformItem instance is automatically created and associated with the DisplayObject. 
		 * If you need to set item-specific settings like minScaleX, maxScaleX, etc., you would set those via the TransformItem 
		 * instance. <code>addItem()</code> returns a TransformItem instance, but you can retrieve it anytime with the <code>getItem()</code>
		 * method (just pass it your DisplayObject, like <code>var myItem:TransformItem = myManager.getItem(myDisplayObject)</code>.
		 * 
		 * @param $targetObject The DisplayObject to be managed
		 * @param $scaleMode Either <code>TransformManager.SCALE_NORMAL</code> for normal scaleX/scaleY scaling or <code>TransformManager.SCALE_WIDTH_AND_HEIGHT</code> if you prefer that FlexTransformManager alters the <code>width</code>/<code>height</code> properties instead.
		 * @param $hasSelectableText If true, this prevents dragging of the object unless clicking on the edges/border or center handle, and allows the DELETE key to be pressed without deleting the object itself. It will also force the scaleMode to <code>TransformManager.SCALE_WIDTH_AND_HEIGHT</code>.
		 * @return TransformItem instance
		 */
		public function addItem($targetObject:DisplayObject, $scaleMode:String="scaleNormal", $hasSelectableText:Boolean=false):TransformItem {
			if ($targetObject.parent != this) {
				super.addChildAt($targetObject, this.numChildren);
			}
			return _manager.addItem($targetObject, $scaleMode, $hasSelectableText);
		}
		
		/**
		 * Same as addItem() but accepts an Array containing multiple DisplayObjects.
		 * 
		 * @param $targetObjects An Array of DisplayObject to be managed
		 * @param $scaleMode Either <code>TransformManager.SCALE_NORMAL</code> for normal scaleX/scaleY scaling or <code>TransformManager.SCALE_WIDTH_AND_HEIGHT</code> if you prefer that FlexTransformManager alters the <code>width</code>/<code>height</code> properties instead.
		 * @param $hasSelectableText If true, this prevents dragging of the objects unless clicking on the edges/border or center handle, and allows the DELETE key to be pressed without deleting the object itself. It will also force the scaleMode to <code>TransformManager.SCALE_WIDTH_AND_HEIGHT</code>.
		 * @return An Array of corresponding TransformItems that are created
		 */
		public function addItems($targetObjects:Array, $scaleMode:String="scaleNormal", $hasSelectableText:Boolean=false):Array	{
			for (var i:int = 0; i < $targetObjects.length; i++) {
				if ($targetObjects[i].parent != this) {
					super.addChild($targetObjects[i]);
				}
			}
			return _manager.addItems($targetObjects, $scaleMode, $hasSelectableText);
		}
		
		
		/**
		 * Adds a child and performs an addItem() so that the new child is managed.
		 * 
		 * @param $child The child DisplayObject
		 * @return DisplayObject
		 */
		override public function addChild($child:DisplayObject):DisplayObject {
			var mc:DisplayObject = super.addChild($child);
			autoAddChild($child);
			return mc;
		}
		
		/** @private **/
		protected function autoAddChild($child:DisplayObject):void {
			var i:int, ignored:Array = _manager.ignoredObjects;
			for (i = 0; i < ignored.length; i++) {
				if (ignored[i] == $child) {
					return;
				}
			}
			if (_manager != null && $child.name != "__dummyBox_mc" && $child.name != "__selection_mc" && $child.name.substr(0, 9) != "__tmProxy") {
				var scaleMode:String = TransformManager.SCALE_NORMAL, hasSelectableText:Boolean = false;
				for (i = _nonStandardScalingClasses.length - 1; i > -1; i--) {
					if ($child is _nonStandardScalingClasses[i].type) {
						scaleMode = _nonStandardScalingClasses[i].scaleMode;
						hasSelectableText = _nonStandardScalingClasses[i].hasSelectableText;
					}
				}
				addItem($child, scaleMode, hasSelectableText);
			}
		}
		
		/**
		 * Adds a child at a particular index and then performs an addItem() to ensure the item is managed
		 * 
		 * @param $child The child DisplayObject to add
		 * @param $index The index number in the display list at which to add the child
		 * @return DisplayObject
		 */
		override public function addChildAt($child:DisplayObject, $index:int):DisplayObject {
			var mc:DisplayObject = super.addChildAt($child, $index);
			autoAddChild($child);
			return mc;
		}
		
		/**
		 * Removes an item. Calling this on an item will NOT delete the DisplayObject - it just prevents it from being affected by this FlexTransformManager anymore.
		 * 
		 * @param $item Either the DisplayObject or the associated TransformItem that should be removed
		 */
		public function removeItem($item:*):void {
			_manager.removeItem($item);
		}
		
		/**
		 * Removes a child DisplayObject
		 * 
		 * @param $child Child to remove
		 * @return DisplayObject
		 */
		override public function removeChild($child:DisplayObject):DisplayObject {
			_manager.removeItem($child);
			return super.removeChild($child);
		}
		
		/**
		 * Removes a child from a particular index number in the display list
		 * 
		 * @param $index Index number from which to remove the child
		 * @return DisplayObject
		 */
		override public function removeChildAt($index:int):DisplayObject {
			_manager.removeItem(this.getChildAt($index));
			return super.removeChildAt($index);
		}
		
		/**
		 * Allows you to have FlexTransformManager ignore clicks on a particular DisplayObject (handy for buttons, color pickers, etc.). The DisplayObject CANNOT be a child of a targetObject
		 * 
		 * @param $object DisplayObject that should be ignored
		 */
		public function addIgnoredObject($object:DisplayObject):void {
			_manager.addIgnoredObject($object);
		}
		
		/**
		 * Removes an ignored DisplayObject so that its clicks are no longer ignored.
		 * 
		 * @param $object DisplayObject that should not be ignored anymore
		 */
		public function removeIgnoredObject($object:DisplayObject):void {
			_manager.removeIgnoredObject($object);
		}
		
		/**
		 * Allows listening for the following events:
		 * <ul>
		 * 		<li> TransformEvent.MOVE
		 * 		<li> TransformEvent.SCALE
		 * 		<li> TransformEvent.ROTATE
		 * 		<li> TransformEvent.SELECT
		 * 		<li> TransformEvent.DELETE
		 * 		<li> TransformEvent.SELECTION_CHANGE
		 * 		<li> TransformEvent.CLICK_OFF
		 * 		<li> TransformEvent.UPDATE
		 * 		<li> TransformEvent.DEPTH_CHANGE
		 * 		<li> TransformEvent.DESTROY
		 * 		<li> TransformEvent.FINISH_INTERACTIVE_MOVE
		 * 		<li> TransformEvent.FINISH_INTERACTIVE_SCALE
		 * 		<li> TransformEvent.FINISH_INTERACTIVE_ROTATE
		 * 		<li> TransformEvent.DOUBLE_CLICK
		 * </ul>
		 * 
		 * @param $type Event type
		 * @param $listener Listener function
		 * @param $useCapture Use capture phase
		 * @param $priority Priority
		 * @param $useWeakReference Use weak reference
		 */
		override public function addEventListener($type:String, $listener:Function, $useCapture:Boolean=false, $priority:int=0, $useWeakReference:Boolean=false):void {
			var isTransform:Boolean = false;
			switch ($type) {
				case TransformEvent.CLICK_OFF:
				case TransformEvent.DELETE:
				case TransformEvent.DEPTH_CHANGE:
				case TransformEvent.DESELECT:
				case TransformEvent.DESTROY:
				case TransformEvent.MOUSE_DOWN:
				case TransformEvent.MOVE:
				case TransformEvent.ROTATE:
				case TransformEvent.SCALE:
				case TransformEvent.SELECT:
				case TransformEvent.SELECTION_CHANGE:
				case TransformEvent.FINISH_INTERACTIVE_MOVE:
				case TransformEvent.FINISH_INTERACTIVE_SCALE:
				case TransformEvent.FINISH_INTERACTIVE_ROTATE:
				case TransformEvent.DOUBLE_CLICK:
				case TransformEvent.UPDATE:
					_manager.addEventListener($type, $listener, $useCapture, $priority, $useWeakReference);
					isTransform = true;
					break;
			}
			if (!isTransform) {
				super.addEventListener($type, $listener, $useCapture, $priority, $useWeakReference);
			}
		}
		
		/**
		 * Removes an Event listener 
		 * 
		 * @param $type Type of Event
		 * @param $listener Listener 
		 * @param $useCapture Use capture phase
		 */
		override public function removeEventListener($type:String, $listener:Function, $useCapture:Boolean=false):void {
			var isTransform:Boolean = false;
			switch ($type) {
				case TransformEvent.CLICK_OFF:
				case TransformEvent.DELETE:
				case TransformEvent.DEPTH_CHANGE:
				case TransformEvent.DESELECT:
				case TransformEvent.DESTROY:
				case TransformEvent.MOUSE_DOWN:
				case TransformEvent.MOVE:
				case TransformEvent.ROTATE:
				case TransformEvent.SCALE:
				case TransformEvent.SELECT:
				case TransformEvent.SELECTION_CHANGE:
				case TransformEvent.FINISH_INTERACTIVE_MOVE:
				case TransformEvent.FINISH_INTERACTIVE_SCALE:
				case TransformEvent.FINISH_INTERACTIVE_ROTATE:
				case TransformEvent.DOUBLE_CLICK:
				case TransformEvent.UPDATE:
					_manager.removeEventListener($type, $listener, $useCapture);
					isTransform = true;
					break;
			}
			if (!isTransform) {
				super.removeEventListener($type, $listener, $useCapture);
			}
		}
		
		/** Removes all children **/
		override public function removeAllChildren():void {
			_manager.removeAllItems();
			super.removeAllChildren();
		}
		
		/**
		 * Selects a particular TransformItem or DisplayObject (you must have already added the DisplayObject
		 * to FlexTransformManager in order for it to be selectable - use <code>addItem()</code> for that)
		 * 
		 * @param $item The TransformItem or DisplayObject that should be selected
		 * @param $addToSelection If true, any currently selected items will remain selected and the new item/DisplayObject will be added to the selection.
		 * @return The TransformItem that was selected.
		 */
		public function selectItem($item:*, $addToSelection:Boolean=false):void {
			_manager.selectItem($item, $addToSelection);
		}
		
		/**
		 * Selects an Array of TransformItems and/or DisplayObjects. (you must have already added the DisplayObjects
		 * to FlexTransformManager in order for it to be selectable - use <code>addItem()</code> or <code>addItems()</code> for that)
		 * 
		 * @param $items An Array of TransformItems and/or DisplayObjects to be selected
		 * @param $addToSelection If true, any currently selected items will remain selected and the new items/DisplayObjects will be added to the selection.
		 * @return An Array of TransformItems that were selected
		 */
		public function selectItems($items:Array, $addToSelection:Boolean=false):void {
			_manager.selectItems($items, $addToSelection);
		}
		
		/**
		 * Deselects a TransformItem or DisplayObject.
		 * 
		 * @param $item The TransformItem or DisplayObject that should be deselected
		 * @return The TransformItem that was deselected
		 */
		public function deselectItem($item:*):void {
			_manager.deselectItem($item);
		}
		
		/** Deselects all items **/
		public function deselectAll():void {
			_manager.deselectAll();
		}
		
		/**
		 * Determines whether or not a particular DisplayObject or TranformItem is currently selected.
		 * 
		 * @param $item The TransformItem or DisplayObject whose selection status needs to be checked
		 * @return If true, the item/DisplayObject is currently selected
		 */
		public function isSelected($item:*):Boolean {
			return _manager.isSelected($item);
		}
		
		/**
		 * Refreshes the selection box/handles. 
		 * 
		 * @param $centerOrigin If true, the origin (axis of rotation/scaling) will be automatically centered.
		 */
		public function updateSelection($centerOrigin:Boolean=true):void {
			_manager.updateSelection($centerOrigin);
		}
		
		/**
		 * Gets the TransformItem associated with a particular DisplayObject (if any). This can be useful if you 
		 * need to set item-specific properties like minScaleX/maxScaleX, etc.
		 * 
		 * @param $targetObject The DisplayObject with which the TransformItem is associated
		 * @return The associated TransformItem
		 */
		public function getItem($targetObject:DisplayObject):TransformItem {
			return _manager.getItem($targetObject);
		}
		
		/** Moves the selection down one level. **/
		public function moveSelectionDepthDown():void {
			_manager.moveSelectionDepthDown();
		}
		
		/** Moves the selection up one level. **/
		public function moveSelectionDepthUp():void {
			_manager.moveSelectionDepthUp();
		}
		
		/**
		 * Gets the center point of the current selection
		 * 
		 * @return Center Point of the current selection
		 */
		public function getSelectionCenter():Point {
			return _manager.getSelectionCenter();
		}
		
		/**
		 * Gets the bounding Rectangle of the current selection (not including handles)
		 * 
		 * @param targetCoordinateSpace The display object that defines the coordinate system to use. 
		 * @return Bounding Rectangle of the current selection (not including handles)
		 */
		public function getSelectionBounds(targetCoordinateSpace:DisplayObject=null):Rectangle {
			return _manager.getSelectionBounds(targetCoordinateSpace);
		}
		
		/**
		 * Gets the bounding Rectangle of the current selection (including handles)
		 * 
		 * @param targetCoordinateSpace The display object that defines the coordinate system to use. 
		 * @return Bounding Rectangle of the current selection (including handles)
		 */
		public function getSelectionBoundsWithHandles(targetCoordinateSpace:DisplayObject=null):Rectangle {
			return _manager.getSelectionBoundsWithHandles(targetCoordinateSpace);
		}
		
		/**
		 * Gets the width of the selection as if it were not rotated.
		 * 
		 * @return The unrotated selection width
		 */
		public function getUnrotatedSelectionWidth():Number {
			return _manager.getUnrotatedSelectionWidth();
		}
		
		/**
		 * Gets the height of the selection as if it were not rotated.
		 * 
		 * @return The unrotated selection height
		 */
		public function getUnrotatedSelectionHeight():Number {
			return _manager.getUnrotatedSelectionHeight();
		}
		
		/**
		 * Moves the selected items by a certain number of pixels on the x axis and y axis
		 * 
		 * @param $x Number of pixels to move the selected items along the x-axis (can be negative or positive)
		 * @param $y Number of pixels to move the selected items along the y-axis (can be negative or positive)
		 * @param $dispatchEvents If false, no MOVE Events will be dispatched
		 */
		public function moveSelection($x:Number, $y:Number, $dispatchEvents:Boolean=true):void {
			_manager.moveSelection($x, $y, $dispatchEvents);
		}
		
		/**
		 * Scales the selected items along the x- and y-axis using multipliers. Keep in mind that these are
		 * not absolute values, so if a selected item's scaleX is 2 and you scaleSelection(2, 1), its new
		 * scaleX would be 4 because 2 * 2 = 4. 
		 * 
		 * @param $sx Multiplier for scaling along the selection box's x-axis (which may or may not be the same as the selected item's y-axis, depending on whether or not multiple items are selected and if any are rotated)
		 * @param $sy Multiplier for scaling along the selection box's y-axis (which may or may not be the same as the selected item's y-axis, depending on whether or not multiple items are selected and if any are rotated)
		 * @param $dispatchEvents If false, no SCALE events will be dispatched
		 */
		public function scaleSelection($sx:Number, $sy:Number, $dispatchEvents:Boolean=true):void {
			_manager.scaleSelection($sx, $sy, $dispatchEvents);
		}
		
		/**
		 * Rotates the selected items by a particular angle (in Radians). This is NOT an absolute value, so if one
		 * of the selected items' rotation property is Math.PI and you <code>rotateSelection(Math.PI)</code>, the new
		 * angle would be Math.PI * 2.
		 * 
		 * @param $angle Angle (in Radians) that should be added to the selected items' current rotation
		 * @param $dispatchEvents If false, no ROTATE events will be dispatched
		 */
		public function rotateSelection($angle:Number, $dispatchEvents:Boolean=true):void {
			_manager.rotateSelection($angle, $dispatchEvents);
		}
		
		/** Destroys the FlexTransformManager instance, removing all items and preparing it for garbage collection **/
		public function destroy():void {
			_manager.destroy();
			_manager = null;
			if (this.parent != null) {
				this.parent.removeChild(this);
			}
		}
		
//---- GETTERS / SETTERS -----------------------------------------------------------------------------------------------------
		
		public function get manager():TransformManager {
			return _manager;
		}
		
		/** Enable or disable the entire FlexTransformManager. **/
		override public function get enabled():Boolean {
			return _manager.enabled;
		}
		override public function set enabled($b:Boolean):void { //Gives us a way to enable/disable all FlexTransformItems
			if (_manager != null) {
				_manager.enabled = $b;
			}
			super.enabled = $b;
		}
		
		/** width **/
		override public function set width($n:Number):void {
			if (this.height != 0) {
				_manager.bounds = new Rectangle(0, 0, $n, this.height);
			} else if (this.parent != null) {
				_manager.bounds = new Rectangle(0, 0, $n, this.parent.height);
			}
			super.width = $n;
		}
		
		/** height **/
		override public function set height($n:Number):void {
			if (this.width != 0) {
				_manager.bounds = new Rectangle(0, 0, this.width, $n);
			} else if (this.parent != null) {
				_manager.bounds = new Rectangle(0, 0, this.parent.width, $n);
			}
			super.height = $n;
		}
		
		/** @private **/
		override public function set verticalScrollPolicy($value:String):void {
			trace("FlexTransformManager must have verticalScrollPolicy set to 'off'.");
		}
		
		/** @private **/
		override public function set horizontalScrollPolicy($value:String):void {
			trace("FlexTransformManager must have horizontalScrollPolicy set to 'off'.");
		}
		
		/** The scaleX of the overall selection box **/
		public function get selectionScaleX():Number {
			return _manager.selectionScaleX;
		}
		public function set selectionScaleX($n:Number):void {
			_manager.selectionScaleX = $n;
		}
		
		/** The scaleY of the overall selection box **/
		public function get selectionScaleY():Number {
			return _manager.selectionScaleY;
		}
		public function set selectionScaleY($n:Number):void {
			_manager.selectionScaleY = $n;
		}
		
		/** The rotation of the overall selection box **/
		public function get selectionRotation():Number {
			return _manager.selectionRotation;
		}
		public function set selectionRotation($n:Number):void {
			_manager.selectionRotation = $n;
		}
		
		/** The x-coordinte of the overall selection box (same as the origin) **/
		public function get selectionX():Number {
			return _manager.selectionX;
		}
		public function set selectionX($n:Number):void {
			_manager.selectionX = $n;
		}
		
		/** The y-coordinte of the overall selection box (same as the origin) **/
		public function get selectionY():Number {
			return _manager.selectionY;
		}
		public function set selectionY($n:Number):void {
			_manager.selectionY = $n;
		}
		
		/** All of the TransformItem instances that are managed by this FlexTransformManager (regardless of whether or not they're selected) **/
		public function get items():Array {
			return _manager.items;
		}
		
		/** All of the targetObjects (DisplayObjects) that are managed by this FlexTransformManager (regardless of whether or not they're selected) **/
		public function get targetObjects():Array {
			return _manager.targetObjects;
		}
		
		/** The currently selected targetObjects (DisplayObjects). For the associated TransformItems, use <code>selectedItems</code>. **/
		public function get selectedTargetObjects():Array {
			return _manager.selectedTargetObjects;
		}
		public function set selectedTargetObjects($a:Array):void {
			_manager.selectedTargetObjects = $a;
		}
		
		/** The currently selected TransformItems (for the associated DisplayObjects, use <code>selectedTargetObjects</code>) **/
		public function get selectedItems():Array {
			return _manager.selectedItems;
		}
		public function set selectedItems($a:Array):void {
			_manager.selectedItems = $a;
		}
		
		/** To constrain items to only scaling proportionally, set this to true [default: <code>false</code>] **/
		public function get constrainScale():Boolean {
			return _manager.constrainScale;
		}
		public function set constrainScale($b:Boolean):void {
			_manager.constrainScale = $b;
		}
		
		/** Prevents scaling [default: <code>false</code>] **/
		public function get lockScale():Boolean {
			return _manager.lockScale;
		}
		public function set lockScale($b:Boolean):void {
			_manager.lockScale = $b;
		}
		
		/** If true, scaling occurs from the center of the selection instead of the corners. [default: <code>false</code>] **/
		public function get scaleFromCenter():Boolean {
			return _manager.scaleFromCenter;
		}
		public function set scaleFromCenter($b:Boolean):void {
			_manager.scaleFromCenter = $b;
		}
		
		/** Prevents rotating [default: <code>false</code>] **/
		public function get lockRotation():Boolean {
			return _manager.lockRotation;
		}
		public function set lockRotation($b:Boolean):void {
			_manager.lockRotation = $b;
		}
		
		/** Prevents moving [default: <code>false</code>] **/
		public function get lockPosition():Boolean {
			return _manager.lockPosition;
		}
		public function set lockPosition($b:Boolean):void {
			_manager.lockPosition = $b;
		}
		
		/** If true, multiple items can be selected (by holding down the SHIFT or CONTROL keys and clicking) [default: <code>true</code>] **/
		public function get allowMultiSelect():Boolean {
			return _manager.allowMultiSelect;
		}
		public function set allowMultiSelect($b:Boolean):void {
			_manager.allowMultiSelect = $b
		}
		
		/** If true, when the user presses the DELETE (or BACKSPACE) key, the selected item(s) will be deleted (except items with <code>hasSelectableText</code> set to true) [default: <code>false</code>] **/
		public function get allowDelete():Boolean {
			return _manager.allowDelete;
		}
		public function set allowDelete($b:Boolean):void {
			_manager.allowDelete = $b;
		}
		
		/** When the user clicks anywhere OTHER than on one of the TransformItems, all are deselected [default: <code>true</code>] **/
		public function get autoDeselect():Boolean {
			return _manager.autoDeselect;
		}
		public function set autoDeselect($b:Boolean):void {
			_manager.autoDeselect = $b;
		}
		
		/** Controls the line color of the selection box and handles [default: <code>0x3399FF</code>] **/
		public function get lineColor():uint {
			return _manager.lineColor;
		}
		public function set lineColor($n:uint):void {
			_manager.lineColor = $n;
		}
		
		/** Controls the fill color of the handle [default: <code>0xFFFFFF</code>] **/
		public function get handleFillColor():uint {
			return _manager.handleFillColor;
		}
		public function set handleFillColor($n:uint):void {
			_manager.handleFillColor = $n;
		}
		
		/** Controls the handle size (in pixels) [default: <code>8</code>] **/
		public function get handleSize():Number {
			return _manager.handleSize;
		}
		public function set handleSize($n:Number):void {
			_manager.handleSize = $n;
		}
		
		/** Determines the amount of space outside each of the four corner scale handles that will trigger rotation mode [default: <code>12</code>] **/
		public function get paddingForRotation():Number {
			return _manager.paddingForRotation;
		}
		public function set paddingForRotation($n:Number):void {
			_manager.paddingForRotation = $n;
		}
		
		/** A Rectangle defining the boundaries for movement/scaling/rotation. [default:null] **/
		public function get bounds():Rectangle {
			return _manager.bounds;
		}
		public function set bounds($r:Rectangle):void {
			_manager.bounds = $r;
		}
		
		/** When true, new selections are forced to the front of the display list of the container DisplayObjectContainer [default: <code>true</code>] **/
		public function get forceSelectionToFront():Boolean {
			return _manager.forceSelectionToFront;
		}
		public function set forceSelectionToFront($b:Boolean):void {
			_manager.forceSelectionToFront = $b;
		}
		
		/** If true, the arrow keys on the keyboard will move the selected items when pressed [default: <code>false</code>] **/
		public function get arrowKeysMove():Boolean {
			return _manager.arrowKeysMove;
		}
		public function set arrowKeysMove($b:Boolean):void {
			_manager.arrowKeysMove = $b;
		}
		
		/** The TransformManager instances associated with this FlexTransformManager **/
		public function get transformManager():TransformManager {
			return _manager;
		}
		
		/** Sometimes you want FlexTransformManager to ignore clicks on certain DisplayObjects, like buttons, color pickers, etc. Those items should populate the ignoreObjects Array. The DisplayObject CANNOT be a child of a targetObject. **/
		public function get ignoredObjects():Array {
			return _manager.ignoredObjects;
		}
		public function set ignoredObjects($a:Array):void {
			_manager.ignoredObjects = $a;
		}
		
		/** To hide the center scale handle, set this to true [default: <code>false</code> **/
		public function get hideCenterHandle():Boolean {
			return _manager.hideCenterHandle;
		}
		public function set hideCenterHandle($b:Boolean):void {
			_manager.hideCenterHandle = $b;
		}
	}
	
}